﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;

using System.Text;
using System.Windows.Forms;
using Common.Utilities;
using Common.Utilities.Test;
using PdfLib;
using PdfLib.TextScraping;

namespace PdfLib.Test.TextScraping
{
    [ManualTestCase("Table conent extractor", "Text scraping")]
    public partial class TestCase_TableDataExtraction : UserControl
    {
        public TestCase_TableDataExtraction()
        {
            InitializeComponent();
        }

        private void btn_Open_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.Filter = "PDF files(*.pdf)|*.pdf|All files(*.*)|*.*";
            if (dlg.ShowDialog() == DialogResult.OK)
            {
                this.txt_PdfPath.Text = dlg.FileName;
                int pageCount = PdfPropertyReader.GetPageCount(this.txt_PdfPath.Text);

                this.OpenPage(this.txt_PdfPath.Text);
            }
        }

        private void btn_Open2_Click(object sender, EventArgs e)
        {
            this.OpenPage(this.txt_PdfPath.Text);
        }

        private void OpenPage(string pdfFilePath)
        {
            
            try
            {
                
                TableHeaderDetectorInstruction headerSetting = this.GetTableHeaderDetectSettings();
                TableFooterDetectorInstruction footerSetting = this.GetTableFooterDetectSettings();
                TableColumnDetectorInstruction colSetting = this.GetColDetectSettings();
                TableRowDetectorInstruction rowSetting=new TableRowDetectorInstruction();
                rowSetting.RelativeMinRowSpacing = (double) this.num_MinLineSpacing.Value;
                rowSetting.DetectRequiredFields = true;
                rowSetting.DetectHyphonWrap = true;

                List<int> pageNumbers=new List<int>();
                int pageCount = PdfPropertyReader.GetPageCount(pdfFilePath);
                for(int pageNum =1; pageNum <= pageCount; pageNum++)
                {
                    double matchScore = 0;
                    PdfPatternSearcher.FoundPattern(
                        pdfFilePath, pageNum, headerSetting.TableHeader, 
                        headerSetting.UseRegexMatch, 0.9, ref matchScore);
                    if(matchScore > 0.9)
                    {
                        bool foundTable = true;
                        foreach(string colHeader in colSetting.ColumnHeadersInFile)
                        {
                            matchScore = 0;
                            PdfPatternSearcher.FoundPattern(
                                pdfFilePath, pageNum, colHeader,
                                false, colSetting.MatchScoreThreshold, ref matchScore);
                            if(matchScore < colSetting.MatchScoreThreshold)
                            {
                                foundTable = false;
                                break;
                            }
                        }
                        if(foundTable)
                        {
                            pageNumbers.Add(pageNum);
                        }
                    }
                }

                Dictionary<int, DataTable> recordsByPages = new Dictionary<int, DataTable>();
                if(pageNumbers.Count>0)
                {
                    foreach(int pageNum in pageNumbers)
                    {
                        if(PdfImageReader.GetPageImage(pdfFilePath, pageNum) !=null)
                        {
                            colSetting.ColumnLayoutDetectionType = ColumnBorderDetectorType.PdfImageRectangle;
                        }
                        else
                        {
                            colSetting.ColumnLayoutDetectionType = ColumnBorderDetectorType.SlidingWindow;
                        }
                        try
                        {
                            Dictionary<string, RectangleF> colHeaderLayout =
                                TableColumnDetector.DetectTableColumnLayouts(
                                    pdfFilePath, pageNum, colSetting);
                            DataTable dtData = TableDetector.ReadTableData(pdfFilePath, pageNum, colHeaderLayout, rowSetting);
                            if (dtData != null && dtData.Rows.Count > 0)
                                recordsByPages.Add(pageNum, dtData);
                        }
                        catch (Exception)
                        {
                        }

                        Image pageImg = PdfTextReader.GetPageTextLayout(pdfFilePath, pageNum);
                        this.pic_PDF.Image = pageImg;
                    }
                }

                DataTable dtOutput = new DataTable();
                foreach(string colHeader in colSetting.ColumnHeadersInFile)
                {
                    dtOutput.Columns.Add(colHeader, typeof (string));
                }
                dtOutput.Columns.Add("PageNumber", typeof (int));
                if(recordsByPages.Count>0)
                {
                    foreach(int pageNum in recordsByPages.Keys)
                    {
                        DataTable dtData = recordsByPages[pageNum];
                        foreach (DataRow dr in dtData.Rows)
                        {
                            DataRow drNew = dtOutput.NewRow();
                            foreach (string colName in colSetting.ColumnHeadersInFile)
                            {
                                drNew[colName] = dr[colName];
                            }
                            drNew["PageNumber"] = pageNum;
                            dtOutput.Rows.Add(drNew);
                        }
                    }
                }

                this.dv_TableData.DataSource = dtOutput;
                this.dv_TableData.Refresh();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        #region settings
        private TableColumnDetectorInstruction GetColDetectSettings()
        {
            TableColumnDetectorInstruction colDetectorSettings = new TableColumnDetectorInstruction();
            colDetectorSettings.MatchScoreThreshold = (double) this.num_MinColHeaderScore.Value;
            colDetectorSettings.AdjustColumnHeaderWidthFromTableRowCount = 5;
            colDetectorSettings.ColumnHeaderSlidingWindwSize = 5;
            colDetectorSettings.ColumnHeadersInFile = new List<string>();
            foreach (DataGridViewRow dr in this.dv_ColHeaders.Rows)
            {
                if (!dr.IsNewRow && dr.Cells[0].Value != null)
                {
                    string colHeader = (string)dr.Cells[0].Value;
                    bool required = false;
                    if(dr.Cells[1].Value !=null)
                        required = (bool)dr.Cells[1].Value;
                    colDetectorSettings.ColumnHeadersInFile.Add(colHeader);
                }
            }
            return colDetectorSettings;
        }

        private void DisplayColDectorSettings(TableColumnDetectorInstruction colDetectSettings)
        {
            this.dv_ColHeaders.Rows.Clear();
            if (colDetectSettings.ColumnHeadersInFile != null && colDetectSettings.ColumnHeadersInFile.Count > 0)
            {
                foreach (string colHeader in colDetectSettings.ColumnHeadersInFile)
                {
                    DataGridViewRow dr = new DataGridViewRow();
                    DataGridViewTextBoxCell cellColHeader = new DataGridViewTextBoxCell();
                    cellColHeader.Value = colHeader;
                    dr.Cells.Add(cellColHeader);
                    DataGridViewCheckBoxCell cellRequired = new DataGridViewCheckBoxCell();
                    bool required = false;
                    cellRequired.Value = required;
                    dr.Cells.Add(cellRequired);
                    this.dv_ColHeaders.Rows.Add(dr);
                }
            }
        }
        
        private TableHeaderDetectorInstruction GetTableHeaderDetectSettings()
        {
            TableHeaderDetectorInstruction headerDetectSetting=new TableHeaderDetectorInstruction();
            headerDetectSetting.MatchScoreThreshold = 0.9;
            headerDetectSetting.PagePositionFilter = null;
            headerDetectSetting.TableHeader = this.txt_HeaderPattern.Text;
            headerDetectSetting.UseRegexMatch = this.ck_HeaderUseRegex.Checked;
            return headerDetectSetting;
        }

        private void DisplayHeaderDetectSettings(TableHeaderDetectorInstruction headerDetectSetting)
        {
            this.txt_HeaderPattern.Text = headerDetectSetting.TableHeader;
            this.ck_HeaderUseRegex.Checked = headerDetectSetting.UseRegexMatch;
        }

        private TableFooterDetectorInstruction GetTableFooterDetectSettings()
        {
            TableFooterDetectorInstruction footerDetectSetting=new TableFooterDetectorInstruction();
            footerDetectSetting.MatchScoreThreshold = 0.9;
            footerDetectSetting.PagePositionFilter = null;
            footerDetectSetting.TableFooter = this.txt_FooterPattern.Text;
            footerDetectSetting.UseRegex = this.ck_FooterUseRegex.Checked;
            footerDetectSetting.TableFooterType = TableFooterType.StringPattern;
            if(this.rd_FooterEOP.Checked)
            {
                footerDetectSetting.TableFooterType = TableFooterType.EndOfPage;
                footerDetectSetting.TableFooter = string.Empty;
            }
            return footerDetectSetting;
        }

        private void DisplayFooterDetectSetting(TableFooterDetectorInstruction footerDetectSetting)
        {
            if(footerDetectSetting.TableFooterType==TableFooterType.EndOfPage)
            {
                this.rd_FooterEOP.Checked = true;
                this.rd_FooterPattern.Checked = false;
            }
            else
            {
                this.rd_FooterEOP.Checked = false;
                this.rd_FooterPattern.Checked = true;
                this.txt_FooterPattern.Text = footerDetectSetting.TableFooter;
                this.ck_FooterUseRegex.Checked = footerDetectSetting.UseRegex;
            }
        }
        #endregion

    }
}
